<!DOCTYPE html>
<html>
  <head>
    <meta http-equiv="Pragma" content="no-cache" />
    <meta http-equiv="Cache-Control" content="no-cache" />
    <meta http-equiv="Expires" content="0" />
    <meta http-equiv="Content-Type" content="text/html;charset=utf-8" />
    <meta
      name="viewport"
      content="width=device-width,initial-scale=1.0,user-scalable=no"
    />
    <title>星空</title>
    <style type="text/css">
      html,
      body {
        height: 100%;
      }

      * {
        margin: 0;
        padding: 0;
      }

      #box {
        position: absolute;
        left: 0;
        top: 0;
        width: 100%;
        height: 100%;
        display: flex;
        justify-content: center;
        align-items: center;
        background: #000;
      }

      .starry {
        position: relative;
        width: 200px;
        height: 500px;
        border: solid #ccc 20px;
        overflow: hidden;
      }

      .bg {
        position: absolute;
        left: 0;
        right: 0;
        top: 0;
        bottom: 0;
      }

      .bg-color {
        background-image: linear-gradient(
          170deg,
          #000093 13%,
          #9f35ff,
          #ff8000 70%,
          #f9f900
        );
      }

      .bg-color2 {
        background-image: linear-gradient(
          180deg,
          #000093 13%,
          #9f35ff,
          #ff8000 80%,
          #f9f900
        );
        opacity: 0.3;
        filter: blur(6px);
      }
      .bg-color3 {
        background: rgba(0,0,0,.2);
      }

      #canvas {
        position: absolute;
        bottom: 150px;
      }
      #shadow {
        position: absolute;
        width: 200px;
        height: 150px;
        bottom: 1px;
        transform: scaleY(-1);
        filter: blur(0.5px);
      }
      .star {
        position: absolute;
        width: 10px;
        height: 10px;
        background: #FFF;
        border-radius: 50%;
      }
      .meteor-box{
        position: absolute;
      }
      .meteor {
        position: relative;
        width: 10px;
        height: 10px;
        background: #fff;
        border-radius: 50%;
        filter: drop-shadow(0 0 5px #fff);
        animation: move 800ms ease-in 1 forwards;
      }
      .meteor::before {
        position: absolute;
        content: '';
        left: 5px;
        top: 0;
        width: 200px;
        height: 10px;
        background-image: linear-gradient(to right,#fff, rgba(255,255,255,0));
      }
      @keyframes move {
        0% {
          transform: translate3d(500px,0,0);
          opacity: 0;
        }
        50% {
          opacity: 1;
        }
        100% {
          transform: translate3d(-500px,0,0);
          opacity: 0;
        }
      }

    </style>
  </head>

  <body bgcolor="#FFFFFF">
    <div id="box">
      <div class="starry" id="starry">
        <div class="bg bg-color"></div>
        <div class="bg bg-color2"></div>
        <div class="bg bg-color3"></div>
        <canvas id="canvas" width="200" height="150"></canvas>
        <canvas id="shadow" width="200" height="150"></canvas>
        <!-- <img id="shadow" /> -->
      </div>
    </div>
    <script>
      var starry = document.getElementById('starry')
      var CANVAS_WIDTH = 200
      var CANVAS_HEIGHT = 150
      // 画布相关
      var canvas = document.getElementById("canvas");
      var ctx = canvas.getContext("2d");      
      var shadow = document.getElementById("shadow");
      var ctxShadow = shadow.getContext("2d");


      ctx.strokeStyle = "#000";
      ctx.lineJoin = "round";
      // 画一棵树
      function drawTree(x, y, deg, step, type) {
        var deg1 = step % 2 == 0 ? 0.1 : -0.1;
        var x1 = x + Math.cos(deg + deg1) * (step + 5) * 0.9;
        var y1 = y + Math.sin(deg + deg1) * (step - 1) * 0.9;
        ctx.beginPath();
        ctx.lineWidth = step / 3;
        ctx.moveTo(x, y);
        ctx.lineTo(x1, y1);
        ctx.stroke();
        if (step > 12) {
          ctx.arc(x, y, step / 6, 0, Math.PI * 2);
          ctx.fill();
        }
        if (step < 3 && Math.random() > 0.7) {
          var r = 2 + Math.random() * 2;
          ctx.arc(x1 + Math.random() * 3, y1 + Math.random() * 3, r, r, Math.PI + r);
          ctx.fill();
        }
        step--;
        if (step > 0) {
          drawTree(x1, y1, deg, step, type);
          if (step % 2 == 1 && step < 17)
            drawTree(x1, y1, deg + 0.2, Math.round(step / 1.13));
          if (step % 2 == 0 && step < 17)
            drawTree(x1, y1, deg - 0.2, Math.round(step / 1.13) );
        }
      }
      // 随便画点草
      function drawGrass(){
        let limit = CANVAS_WIDTH, x, y
        for(var i = 0 ; i < limit ; i ++) {
          ctx.beginPath()
          ctx.lineWidth = 0.6 + Math.random()
          ctx.moveTo(i - 5 + Math.random()*10, 135 + Math.random() * 20)
          ctx.lineTo(i,150)
          ctx.lineTo(i - 10 + Math.random()*20, 130 + Math.random() * 20)
          ctx.stroke()
        }
      }
      // 画倒影
      function drawShadow(){
        var imgData = ctx.getImageData(0,0,CANVAS_WIDTH,CANVAS_HEIGHT)
        var line = 0
        var pos = 0
        var dark = false
        // 增加一点杂色
        for(var y = 0 ; y < CANVAS_HEIGHT ; y ++) {
          for(var x = 0 ; x < CANVAS_WIDTH ; x ++) {
            if(line <= 0 && Math.random() > 0.9995) {
              line = Math.random() * 10 + 10
              dark = [true,false][Math.round(Math.random())]
            }
            if(line > 0) {
              pos = (y * CANVAS_WIDTH + x) * 4
              imgData.data[pos + 0] = dark ? 0 : 255
              imgData.data[pos + 1] = dark ? 0 : 255
              imgData.data[pos + 2] = dark ? 0 : 255
              imgData.data[pos + 3] = 90
            }
            line --
          }
        }
        var startWave = 0 // 水波起始位置
        // 倒影增加水波纹效果
        function wave(star){
          var newImgData = ctxShadow.createImageData(200,150)
          var pos = 0
          var source = 0
          startWave += 0.2
          start = startWave
          for(var y = 0 ; y < CANVAS_HEIGHT ; y ++) {
            start += 0.5
            for(var x = 0 ; x < CANVAS_WIDTH ; x ++) {
              pos = (y * CANVAS_WIDTH + x) * 4
              source = (y * CANVAS_WIDTH + x + Math.round(Math.sin(start)* 1.5)) * 4
              newImgData.data[pos + 0] = imgData.data[source + 0];
              newImgData.data[pos + 1] = imgData.data[source + 1];
              newImgData.data[pos + 2] = imgData.data[source + 2];
              newImgData.data[pos + 3] = imgData.data[source + 3];
            }
          }
          ctxShadow.putImageData(newImgData,0,0)
          requestAnimationFrame(wave)
        }
        wave()
      }
      // 随便画一些星星
      function drawStar(){
        var limit = 40
        var fragment = document.createDocumentFragment()
        for(var i = 0 ; i < limit ; i ++) {
          var div = document.createElement('div')
          div.className = 'star'
          div.style.left = ~~(Math.random() * CANVAS_WIDTH) + 'px'
          div.style.top = ~~(Math.random() * CANVAS_WIDTH) + 'px'
          div.style.transform = 'scale('+ (Math.random() * 0.1 + 0.1)+')'
          div.style.opacity = Math.random()*0.6 + 0.4
          fragment.appendChild(div)
        }
        starry.appendChild(fragment)
      }
      // 偶尔来一个流星
      function drawMeteor(){
        setInterval(function(){
          var box = document.createElement('div')
          box.className = 'meteor-box'
          box.style.left = ~~(Math.random() * CANVAS_WIDTH/2) + 'px'
          box.style.top = ~~(Math.random() * CANVAS_WIDTH/2) + 'px'
          box.style.transform = 'scale('+ (Math.random() * 0.1 + 0.05)+') rotate('+ ~~(Math.random()*30 - 45)+'deg)'
          box.innerHTML = '<div class="meteor"></div>'
          starry.appendChild(box)
          setTimeout(function(){
            starry.removeChild(box)
          },800)
        },2000)
      }
      window.onload = function(){
        drawTree(canvas.width/3*2,150,-Math.PI/2,18,1)
        drawGrass()
        drawShadow()
        drawStar()
        drawMeteor()
        /*
        var imgData = canvas.toDataURL()
        var img = document.getElementById('shadow')
        img.src = imgData*/
      }
    </script>
  </body>
</html>
